#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "Jeu.h"



/**
 * \fn void jeuInit(Jeu *pJeu)
 * \brief Initialise les snakes et le terrain nécessaires pour le jeu
 * \param [in,out] pJeu Jeu initialisé par jeuInit
 */

void jeuInit(Jeu *pJeu)
{
	snake1Init(&(pJeu->snake1));
	snake2Init(&(pJeu->snake2));
	terrainInit(&(pJeu->terrain));
}



/**
 * \fn void jeuLibere(Jeu *pJeu)
 * \brief Libère la mémoire utilisée par le tableau de jeu
 * \param [in,out] pJeu Jeu dont on va libérer la mémoire
 */

void jeuLibere(Jeu *pJeu)
{
	terrainLibere(&(pJeu->terrain));
}

/**
 * \fn void remplirTableau(Jeu *pJeu, int x, int y)
 * \brief remplit le terrain avec une * si n snake passe sur une case vide
 * \param [in,out] pJeu Jeu dans lequel est le snake
 * \param [in] x entier abscisse du terrain où se déplace le snake
 * \param [in] y entier ordonnée du terrain où se déplace le snake
 */

void remplirTableau(Jeu *pJeu, int x, int y)
{
    pJeu->terrain.tab[y][x]='*';
}



/**
 * \fn const Terrain *jeuGetConstTerrainPtr(const Jeu *pJeu)
 * \brief récupère un pointeur sur terrrain
 * \param [in,out] pJeu const Jeu dont on va récupérer l'adresse du terrain
 */

const Terrain *jeuGetConstTerrainPtr(const Jeu *pJeu)
{
	return &(pJeu->terrain);
}


/**
 * \fn const Snake *jeuGetConstSnake1Ptr(const Jeu *pJeu)
 * \brief récupère un pointeur sur le premier snake
 * \param [in,out] pJeu const Jeu dont on va récupérer l'adresse du premier snake
 */

const Snake *jeuGetConstSnake1Ptr(const Jeu *pJeu)
{
	return &(pJeu->snake1);
}



/**
 * \fn const Snake *jeuGetConstSnake2Ptr(const Jeu *pJeu)
 * \brief récupère un pointeur sur le deuxième snake
 * \param [in,out] pJeu const Jeu dont on va récupérer l'adresse du deuxième snake
 */

const Snake *jeuGetConstSnake2Ptr(const Jeu *pJeu)
{
	return &(pJeu->snake2);
}




/**
 * \fn void jeuActionClavier(Jeu *pJeu, const char touche)
 * \brief fonction pour savoir qeulle action exécuter en fonction de la touche entrée
 * \param [in,out] pJeu Jeu dans lequel l'action a été effectuée
 * \param [in] touche touche rentrée par l'utilisateur
 */

void jeuActionClavier(Jeu *pJeu, const char touche)
{
    if(touche == 'g' && (pJeu->snake1.sens) != 0 && (pJeu->snake1.sens) != 1)
    {
        snakeGauche(&(pJeu->snake1), &(pJeu->terrain));
    }

    if(touche == 'd' && (pJeu->snake1.sens) != 0 && (pJeu->snake1.sens) != 1)
    {
        snakeDroite(&(pJeu->snake1), &(pJeu->terrain));
    }

    if(touche == 'h' && (pJeu->snake1.sens) != 2 && (pJeu->snake1.sens) != 3)
    {
        snakeHaut(&(pJeu->snake1), &(pJeu->terrain));
    }

    if(touche == 'b' && (pJeu->snake1.sens) != 2 && (pJeu->snake1.sens) != 3)
    {
        snakeBas(&(pJeu->snake1), &(pJeu->terrain));
    }

    if(touche == 'G' && (pJeu->snake2.sens) != 0 && (pJeu->snake2.sens) != 1)
    {
        snakeGauche(&(pJeu->snake2), &(pJeu->terrain));
    }

    if(touche == 'D' && (pJeu->snake2.sens) != 0 && (pJeu->snake2.sens) != 1)
    {
        snakeDroite(&(pJeu->snake2), &(pJeu->terrain));
    }

    if(touche == 'H' && (pJeu->snake2.sens) != 2 && (pJeu->snake2.sens) != 3)
    {
        snakeHaut(&(pJeu->snake2), &(pJeu->terrain));
    }

    if(touche == 'B' && (pJeu->snake2.sens) != 2 && (pJeu->snake2.sens) != 3)
    {
        snakeBas(&(pJeu->snake2), &(pJeu->terrain));
    }
}


/**
 * \fn const Bonus *jeuGetConstBonusPtr(const Jeu *pJeu)
 * \brief récupère un pointeur sur un bonus
 * \param [in,out] pJeu const Jeu dans lequel est le bonus
 */

Bonus *jeuGetConstBonusPtr(Jeu *pJeu)
{
    return &(pJeu->bonus);
}



/**
 * \fn void jeuEvolue(Jeu *pJeu)
 * \brief fonction qui gère l'évolution du jeu et effectue les actions nécessaires
 * \param [in,out] pJeu const Jeu sur lequel on effectue les actions
 */

void jeuEvolue(Jeu *pJeu)
{
    int testx1, testy1, testx2, testy2;
    Snake *pSnake1;
    Snake *pSnake2;
    int depx[] = {-1, 1, 0, 0};
    int depy[] = {0, 0, -1, 1};
    pSnake1 = &(pJeu->snake1);
    pSnake2 = &(pJeu->snake2);
    testx1 = pSnake1->x + depx[pSnake1->sens];
    testy1 = pSnake1->y + depy[pSnake1->sens];
    testx2 = pSnake2->x + depx[pSnake2->sens];
    testy2 = pSnake2->y + depy[pSnake2->sens];
    if(posPersoValide(&(pJeu->terrain), testx1, testy1)
    && posPersoValide(&(pJeu->terrain), testx2, testy2))
    {
        remplirTableau(pJeu, pSnake1->x, pSnake1->y); /*Si les deux deplacements sont valides,*/
        pSnake1->x = testx1;                          /*on remplit le tableau pour garder les coordonnées*/
        pSnake1->y = testy1;                          /*où étaient les serpents, et on donne les nouvelles*/
                                                      /*coordonnées des serpents*/
        remplirTableau(pJeu, pSnake2->x, pSnake2->y);
        pSnake2->x = testx2;
        pSnake2->y = testy2;

        /*if (pJeu->bonus.x == testx1 && pJeu->bonus.y == testy1)     Si les coordonnées sont celles d'un bonus
        {                                                             on fait l'action associée au bonus
            snakeBonus(pSnake1, &(pJeu->bonus), &(pJeu->terrain));
        }

        if (pJeu->bonus.x == testx2 && pJeu->bonus.y == testy2)
        {
            snakeBonus(pSnake2, &(pJeu->bonus), &(pJeu->terrain));
        }*/
    }

    if (!posPersoValide(&(pJeu->terrain), testx1, testy1) &&
    posPersoValide(&(pJeu->terrain), testx2, testy2))
    {
        pJeu->score2 = pJeu->score2 + 1;    /* Si le déplacement de Snake1 est invalide*/
        snake1Init(pSnake1);                /* On incremente le score de Snake2*/
        snake2Init(pSnake2);                /* et on reinitialise les snakes et le terrain*/
        terrainInit(&(pJeu->terrain));      /* puis on incremente afficherTerrain, qui permet*/
        pJeu->afficherTerrain = 1;          /* de reafficher le terrain vierge en SDL*/
    }

    if(posPersoValide(&(pJeu->terrain), testx1, testy1) && !posPersoValide(&(pJeu->terrain), testx2, testy2))
    {
        pJeu->score1 = pJeu->score1 + 1;    /* Si le déplacement de Snake2 est invalide*/
        snake1Init(pSnake1);                /* On incremente le score de Snake1*/
        snake2Init(pSnake2);                /* et on reinitialise les snakes et le terrain*/
        terrainInit(&(pJeu->terrain));      /* puis on incremente afficherTerrain, qui permet*/
        pJeu->afficherTerrain = 1;          /* de reafficher le terrain vierge en SDL*/
    }
    if(!posPersoValide(&(pJeu->terrain), testx1, testy1) && !posPersoValide(&(pJeu->terrain), testx2, testy2))
    {
        snake1Init(pSnake1);              /* Si les deux déplacements sont invalides*/
        snake2Init(pSnake2);              /* on reinitialise les snakes et le terrain*/
        terrainInit(&(pJeu->terrain));    /* puis on incremente afficherTerrain*/
        pJeu->afficherTerrain = 1;
    }
    if(testx1==testx2 && testy1==testy2)
    {
        snake1Init(pSnake1);                /* Pareil si les deux serpents se fonce dedans*/
        snake2Init(pSnake2);
        terrainInit(&(pJeu->terrain));
        pJeu->afficherTerrain = 1;
    }
}

